{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6c3cf512",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.cluster import KMeans\n",
    "from sklearn.metrics import calinski_harabasz_score, silhouette_score, davies_bouldin_score\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "\n",
    "# 读取表格数据\n",
    "data = pd.read_excel('Kmeans++数据集.xlsx', index_col=0)\n",
    "\n",
    "# 提取特征列和样本行\n",
    "features = data.columns\n",
    "samples = data.index\n",
    "\n",
    "# 标准化\n",
    "scaler = StandardScaler()\n",
    "data = scaler.fit_transform(data)\n",
    "\n",
    "# 初始化空列表\n",
    "chs = []\n",
    "sse_values = []\n",
    "sil_scores = []\n",
    "db_scores = []\n",
    "\n",
    "# 进行不同K值的聚类分析\n",
    "k_values = range(2,21)  # K值的范围：根据实际情况确定聚类范围\n",
    "for k in k_values:\n",
    "    # 使用kmeans++聚类算法\n",
    "    kmeans = KMeans(n_clusters=k, init='k-means++', random_state=2023)\n",
    "    kmeans.fit(data)\n",
    "    sse_values.append(kmeans.inertia_)\n",
    "    \n",
    "    # 计算Calinski-Harabasz分数\n",
    "    ch = calinski_harabasz_score(data, kmeans.labels_)\n",
    "    chs.append(ch)\n",
    "    \n",
    "    # 计算轮廓系数\n",
    "    sil_score = silhouette_score(data, kmeans.labels_)\n",
    "    sil_scores.append(sil_score)\n",
    "    \n",
    "    # 计算Davies-Bouldin分数\n",
    "    db_score = davies_bouldin_score(data, kmeans.labels_)\n",
    "    db_scores.append(db_score)\n",
    "\n",
    "# ******************绘制肘部法则的折线图*******************\n",
    "plt.plot(k_values, sse_values,'r-')\n",
    "plt.xlabel('Number of clusters K')\n",
    "plt.ylabel('distortions')\n",
    "plt.scatter(k_values, sse_values, marker='^', color='blue')\n",
    "plt.xticks(range(0, 21, 2))\n",
    "plt.show()\n",
    "\n",
    "# *********绘制不同K值下的Calinski-Harabasz柱状图**********\n",
    "plt.bar(k_values, chs)\n",
    "plt.xlabel('Number of clusters K')\n",
    "plt.ylabel('Calinski-Harabasz Score')\n",
    "plt.ylim(1100, 1280) \n",
    "plt.xticks(range(0, 21, 2))\n",
    "# 待改进：将最大的chs的柱子改成红色\n",
    "plt.bar(12, chs[10], color='red')   \n",
    "# 标注每个数据点的数值\n",
    "for i in range(len(chs)):\n",
    "    plt.text(k_values[i], chs[i], f'{chs[i]/1000:.2f}K', ha='center', va='bottom', fontsize=6)\n",
    "plt.show()\n",
    "\n",
    "# 根据Calinski-Harabasz指标选择最佳K值\n",
    "best_k = k_values[np.argmax(chs)]\n",
    "\n",
    "# 根据最佳K值重新进行聚类\n",
    "best_kmeans = KMeans(n_clusters=best_k, init='k-means++')\n",
    "best_kmeans.fit(data)\n",
    "\n",
    "# 查看聚类中心\n",
    "cluster_centers = pd.DataFrame(best_kmeans.cluster_centers_, columns=features)\n",
    "print(\"聚类中心:\")\n",
    "print(cluster_centers)\n",
    "\n",
    "# 计算最佳K值下的CHI、轮廓系数和Davies-Boeldin的值\n",
    "best_ch = calinski_harabasz_score(data, best_kmeans.labels_)\n",
    "best_sil_score = silhouette_score(data, best_kmeans.labels_)\n",
    "best_db_score = davies_bouldin_score(data, best_kmeans.labels_)\n",
    "# 打印结果\n",
    "print(\"Calinski-Harabasz Score:\", best_ch)\n",
    "print(\"Silhouette Score:\", best_sil_score)\n",
    "print(\"Davies-Bouldin Score:\", best_db_score)\n",
    "\n",
    "# 将分类结果保存到另一个表格\n",
    "# 待改进——>保存到另外一个表格：第一列：样本；第二列：分类\n",
    "cluster_labels = pd.DataFrame(best_kmeans.labels_, columns=['分类']) \n",
    "cluster_labels.to_excel('clustered_data.xlsx')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
